'''数据获取'''
#导包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#忽略警告
import warnings
warnings.filterwarnings('ignore')
#避免画图乱码问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

#导入数据
train = pd.read_csv('./一刀切型散点/train.csv',header=None)
test = pd.read_csv('./一刀切型散点/test.csv',header=None)

#提取样本和target
x_train=train.iloc[0:2,:].T
y_train=train.iloc[-1,:].T
x_test=test.iloc[0:2,:].T
y_test=test.iloc[-1,:].T

'''建立模型'''
def sigmoid(z):
    h=1/(1+np.exp(-z))
    return h

#cost function
def costF(X,y,theta):
    hx = sigmoid(X.dot(theta))
    left = y*np.log(hx)
    right = (1-y)*np.log(1-hx)
    return -np.sum(left+right)/len(X)

#梯度下降
def DradientDescent(X,y,theta,alpha,iterations):
    m = len(X)
    for i in range(iterations):
        gradient = np.dot(X.T,sigmoid(X.dot(theta))-y)/m
        theta = theta - alpha*gradient
    return theta

#算出最优权重值
x_train.insert(0,'ones',1)
theta = np.zeros((len(x_train.columns),1))
alpha = 0.05
iterations = 100001
y_train=y_train.values.reshape(len(y_train),1)
w = DradientDescent(x_train,y_train,theta,alpha,iterations)

#确立模型
def fx(x):
    y=-(w[1]*x+w[0])/w[2]
    return y

'''数据可视化'''
#可视化
data= np.array(test).transpose([1,0])
fig,ax = plt.subplots()
fig= plt.subplot(111)
fig.spines['bottom'].set_position(('data',0))
fig.spines['left'].set_position(('data',0))
fig.spines['top'].set_color(None)
fig.spines['right'].set_color(None)
x1=test.iloc[0,:]
x2=-(w[1]*x1+w[0])/w[2]
ax.plot(x1,x2,label='prediction')
for point in data:
    fig.scatter(point[0],point[1],color='r' if(point[2]==1) else 'b')
ax.legend()
plt.show()

'''评估算法'''
# 混淆矩阵
TP, FN, FP, TN = 0, 0, 0, 0
for i in range(len(y_test)):
    if x_test.iloc[:, 1][i] > fx(x_test.iloc[:, 0][i]) and y_test.values[i] == 1:
        TP += 1
    elif x_test.iloc[:, 1][i] > fx(x_test.iloc[:, 0][i]) and y_test.values[i] == 0:
        FN += 1
    elif x_test.iloc[:, 1][i] < fx(x_test.iloc[:, 0][i]) and y_test.values[i] == 1:
        FP += 1
    elif x_test.iloc[:, 1][i] < fx(x_test.iloc[:, 0][i]) and y_test.values[i] == 0:
        TN += 1

print("TP：", TP)
print("FN：", FN)
print("FP：", FP)
print("TN：", TN)

def assess(TP, FN, FP, TN):
    # 准确率
    Accuracy = (TP + TN) / (TP + FP + TN + FN)
    # 精确率
    Precision = TP / (TP + FP)
    # 召回率
    Recall = TP / (TP + FN)
    # F1
    F1 = (2 * Precision * Recall) / (Precision + Recall)

    print("Accuracy：", Accuracy)
    print("Precision：", Precision)
    print("Recall：", Recall)
    print("F1：", F1)
    return

assess(TP, FN, FP, TN)